<?php
namespace console\controllers; 
use Yii;
use common\models\StaticInstance;
use common\models\tradeModel;
use common\utils\CommonFun;
use common\models\Balance;
use common\models\BalanceType;
use common\models\Setting;
use common\models\Member;
use common\models\EthTradeLog;
use common\models\TradeRecharge;

use xtype\Ethereum\Client;
use xtype\Ethereum\Utils;
/*
	* 以太坊交易相关定时
*/
class EthTradeController extends CoreController
{
	protected $client;

	## 扫描交易  php /www/wwwroot/lcl_trade/yii eth-trade/scan-trade >> /www/wwwroot/lcl_trade/logs/scan.txt
	public function actionScanTrade()
	{
		//实例化连接对象
		$this->client = new Client(Yii::$app->params['eth']['infuraUrl']);        

		//获取最新区块高度
		$newBlock = $this->client->eth_blockNumber(); 
		// //转化为10进制的
		$newBlockDec = Utils::hexToDec($newBlock);  
		$newBlockDec = $newBlockDec - 6;

		//上次存储的区块高度
		$oldBlock = Setting::getValue('eth','block_height'); 

		if($newBlockDec<$oldBlock) return false;
		## 记录高度 
		$str = '';
		for($i=$oldBlock;$i<=$newBlockDec;$i++){
			$str .= $i.',';
		}
		$date = date("Y-m-d");
		file_put_contents(Yii::$app->params['logPath'].'/height/'.$date.'.txt', $str, FILE_APPEND); 

		$contractAddress = Yii::$app->params['eth']['usdtContractAddress'];
		$apiKey = Yii::$app->params['eth']['apiKey'];
		$url = 'https://api.etherscan.io/api?module=account&action=tokentx&contractaddress='.$contractAddress.'&startblock='.$oldBlock.'&endblock='.$newBlockDec.'&sort=asc&apikey='.$apiKey;
		$res = file_get_contents($url);
		$res = json_decode($res,1);

		if($res['status']!='1' || !$res['result']) return true;  //$res['message']!='OK' || 

		//获取区块的交易数据
		$transactions = $res['result'];
		if(!$transactions) return false;;
		$this->proccessTransaction($transactions); 
		//存储当前高度
		Setting::setValue('eth','block_height',$newBlockDec+1);
		return true;
	}


	//处理交易 
	private function proccessTransaction($transactions)
	{   

		foreach($transactions as $tradeInfo)  
		{
			//收款地址
			$toAddress = $tradeInfo['to'];
			
			if($toAddress== null) continue;
			$toAddress = strtolower($toAddress);

			//input data
			$inputData = $tradeInfo['input'];

			//value 值 表示数量
			$value = $tradeInfo['value'];
			if($inputData=='0x' || $value>0) 
			{
				$nums = $value/pow(10,$tradeInfo['tokenDecimal']);
				//执行业务
				$this->addTransactionLog($tradeInfo,$toAddress,$nums);
			}else
			{
				//非ETH交易 需要解析input data  这种情况 上面的to表示的是合约地址，而不是收款地址
				//收款地址
				$inputData = str_replace('0xa9059cbb','',$inputData);

				$toAddress = strtolower("0x".substr($inputData,24,40));	

				//交易数量
				
				$numData = substr($inputData,64,64);    
				$nums = Utils::hexToDec($numData);
				$nums = $nums/pow(10,6); 	  
				//执行业务
				$this->addTransactionLog($tradeInfo,$toAddress,$nums);						
			}
		}
	}


	//将转入到系统会员地址的交易记录到日志中，等12个区块区后，再执行具体操作
	private function addTransactionLog($tradeInfo,$toAddress,$nums)
	{
		//判断转入的地址，是否存在我们系统中
		$member = Member::find()->select(['member_id'])->where(["address"=>$toAddress])->asarray()->one();
		if(!$member) return false;

		$where = ['member_id'=>$member['member_id'],'hash' => $tradeInfo['hash']];
		$log = EthTradeLog::find()->where($where)->asarray()->one();
		if($log) return true; 

		//添加到日志
		$data = array(
			'member_id'		=> $member['member_id'],
			'block_hash'	=> $tradeInfo['blockHash'],   
			'block_number'	=> $tradeInfo['blockNumber'], 
			'from_address'	=> $tradeInfo['from'],
			'to_address'	=> $toAddress, 
			'hash'			=> $tradeInfo['hash'], 
			'value'			=> $nums,
			'nonce'			=> $tradeInfo['nonce'],
			'data'			=> json_encode($tradeInfo),
			'status'		=> 0,
			'create_time'	=> time()
		);
		$model = new EthTradeLog;
		$flag  = $model->load($data,'') && $model->save();
		if(!$flag) var_dump($model->errors);
		return $flag;
	}


	

	#####################################  交易处理 ######################################
	## 交易处理  12个区块之后 将转入的币 进入到系统
	public function actionTradeProccess()
	{
		$this->client = new Client(Yii::$app->params['eth']['infuraUrl']);  

		//获取当前存储的区块高度
		$newBlock = Setting::getValue('eth','block_height');

		//12个区块之后 ，更新数据
		$newBlock = $newBlock - 12;

		$data = EthTradeLog::find()->where(['status'=>'0'])->andWhere(['<=','block_number',$newBlock])->asarray()->all();
		if(!$data) return true;

		//充值配置信息
		$where = ['mch_id'=>0];
		$conf = TradeRecharge::getOne($where);

		foreach($data as $val)
		{
			//验证是否到账
			$res = $this->client->eth_getTransactionReceipt($val['hash']);
			$status = Utils::hexToDec($res->status);
			if($status=='1') $this->theNextBonus($val,$conf);
		}
	}


	private function theNextBonus($val,$conf)
	{
		$transaction = Yii::$app->db->beginTransaction();

		//充值到平台
		$btype = isset($conf['b_type'])?$conf['b_type']:1;
		$res = Balance::addBalance($val['member_id'],$btype,$val['value'],4,$val['id']);

		//更新状态
		$updateData = array('update_time'=>time(),'status'=>'1');
		$flag1 = EthTradeLog::updateAll($updateData,['id'=>$val['id']]);
		
		$flag = $res['state']&&$flag1;
		if($flag)
		{
			$transaction->commit();		
			return true;
		}else
		{
			$transaction->rollback();
			return false;
		}
	}	


}